package com.zw.a.basic.a13.demo03_tickets;

//自定义的线程类MyThread, 用来实现模拟卖票
public class MyThread extends Thread {
    //1. 定义变量, 记录票数.
    private static int tickets = 100;      //细节1: 这里要加static, 以为4个窗口(线程)共享100张票.

    //定义构造方法, 用来给线程设置名字.
    public MyThread() {
    }

    public MyThread(String name) {
        super(name);
    }

    //2. 在run()方法中实现模拟卖票
    @Override
    public void run() {
        //3.一直卖票,  没有票, 就不卖了.
        while(true) {
            // 没有票, 就不卖了.
            if (tickets <= 0) {         //线程1,线程2 线程3, 线程4
                break;
            }

            //细节2: 加入休眠线程, 让程序出错的概率大一些.
            try {
                Thread.sleep(50);   //单位是毫秒,  该方法的特点是: 在哪里睡, 到点后就在哪里醒来.     线程1,线程2 线程3, 线程4
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            //走到这里, 说明有票, 卖票即可
            System.out.println(getName() + "  售卖出第 "+ tickets-- +" 张票");    //细节3: 这里要加入线程名, 即: 那个窗口卖的票.
        }

        /*
            出现负数票的原因是因为: 当tickets的值等于1的时候, 此时如果4个线程都抢到了资源, 就会全部越过if校验, 情况如下:
                假设 线程1 先醒来, 此时打印:  售卖出第 1 张票,  然后执行tickets--, 此时tickets的值为: 0
                假设 线程2 后醒来, 此时打印:  售卖出第 0 张票,  然后执行tickets--, 此时tickets的值为: -1
                假设 线程3 后醒来, 此时打印:  售卖出第 -1 张票,  然后执行tickets--, 此时tickets的值为: -2
                假设 线程4 后醒来, 此时打印:  售卖出第 -2 张票,  然后执行tickets--, 此时tickets的值为: -3

            出现重复值的原因:   核心点在tickets--这行代码上, 该代码相当于:  tickets = tickets - 1, 它做了 3 件事:
                1. 读值. 读取tickets的值, 假设为 43
                2. 改值. 将tickets的值 -1, 变为: 42
                3. 赋值. 将42重新赋值给变量 tickets.

                当还没有来得及做第3件事(赋值)的时候, 被其他线程抢走资源了, 此时打印的就是重复值.
         */
    }
}
